package com.hz.basic.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hz.basic.component.SmsComponent;
import com.hz.basic.entity.*;
import com.hz.basic.service.*;
import com.hz.basic.web.LoginTeacherEntity;
import com.hz.basic.web.LoginUserEntity;
import com.hz.common.utils.ResponseData;
import com.hz.utils.MacUtils;
import com.hz.utils.UserLoginState;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.concurrent.TimeUnit;


@RestController
@RequestMapping("user")
@Api(tags = "用户")
public class UserController {

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    private TeacherService userService;

    @Autowired
    private MacAddressService macAddressService;

    @Autowired
    private TeacherConfigService teacherConfigService;

    @Autowired
    private ActivecodeService activecodeService;

    @Autowired
    private CbPcsystemEditionService pcsystemEditionService;

    @Autowired
    private CityService cityService;

    @Resource
    private SmsComponent smsComponent;

    @ApiOperation("通过密码登录")
    @PostMapping("/login")
    public ResponseData<JSONObject> login(@RequestBody LoginUserEntity loginUser, HttpSession session) {
        //密码账号不能为空
        if(loginUser.getPassword().equals("") || loginUser.getPhone().equals(""))
            return ResponseData.success(UserLoginState.ACCOUNTPWD_NOT_NULL, false);
        //非法MAC地址
        if (!MacUtils.verificateMAC(loginUser.getMac()))
            return ResponseData.success(UserLoginState.MAC_FORMAT_ERROR, false);

        // 体验账号 系统生成账号 激活账号
        if (!userService.checkMobileUnique(loginUser.getPhone())) {
            // 手机号没有注册
            return ResponseData.success(UserLoginState.ACCOUNT_NOTEXIT, false);
        }

        TeacherEntity userEntity = userService.pwdlogin(loginUser);
        // 判断账号是否过期或禁用
        if (userEntity == null) {
            // 登录失败
            return ResponseData.success(UserLoginState.PWD_ERROR, false);
        } else if (userEntity.getStatus() == 0) {
            // 账号禁用
            return ResponseData.success(UserLoginState.ACCOUNT_LOCKOREXPIRE, false);
        }
        Date stoptime = userEntity.getStoptime() == null?new Date():userEntity.getStoptime();
        Date nowtime = new Date();
        if (stoptime.compareTo(nowtime) == -1) {
            //账号过期
            return ResponseData.success(UserLoginState.ACCOUNT_LOCKOREXPIRE, false);
        }
        // 验证mac地址
        if (userEntity.getUserType() == 2 || userEntity.getUserType() == 1) {
            // Mac地址是否运行
            MacAddressEntity mac = macAddressService.getOne(new QueryWrapper<MacAddressEntity>().eq("user_id", userEntity.getId()).eq("mac_address", loginUser.getMac()).last("limit 1"));
            if (mac == null) {
                // mac地址不存在
                if (userEntity.getMacStatus() == 0) {
                    //禁止mac添加
                    return ResponseData.success(UserLoginState.MAC_TOKEN_ERROR, false);
                } else if (userEntity.getMacStatus() == 1) {
                    // 获取开启的mac地址的数量
                    int number = macAddressService.list(new QueryWrapper<MacAddressEntity>().eq("user_id", userEntity.getId()).eq("allow", "1")).size();
                    if(number >= 2)  return ResponseData.success(UserLoginState.MAC_TOKEN_ERROR, false);
                    // 获取总共的mac地址的数量
                    number = macAddressService.list(new QueryWrapper<MacAddressEntity>().eq("user_id", userEntity.getId())).size();
                    if(number >= 4)  return ResponseData.success(UserLoginState.MAC_TOKEN_ERROR, false);
                    //开启mac修改且不存在
                    //添加mac地址
                    MacAddressEntity macAddressEntity = new MacAddressEntity();
                    macAddressEntity.setCreateTime(new Date());
                    macAddressEntity.setUserId(userEntity.getId());
                    macAddressEntity.setMacAddress(loginUser.getMac());
                    macAddressEntity.setAllow(1);
                    macAddressService.save(macAddressEntity);
                }
            }else if(mac.getAllow() == 0){
                //mac地址是否运行访问
                return  ResponseData.success(UserLoginState.MAC_TOKEN_ERROR, false);
            }
            //记录用户登录日志
            TeacherConfigEntity teacherConfigEntity = new TeacherConfigEntity();
            Date date = new Date();
            teacherConfigEntity.setIncreatetime(date);
            teacherConfigEntity.setOutcreatetime(date);
            teacherConfigEntity.setTotaltime(0);
            teacherConfigEntity.setTeacherId(userEntity.getId());
            teacherConfigEntity.setStatus(1);
            teacherConfigService.save(teacherConfigEntity);
        }
        //校验成功正常访问
        //登录成功
        String loginToken = session.getId() + ":" + userEntity.getId();
        redisTemplate.opsForValue().set("user:" + loginToken, userEntity.getId() + "", 2, TimeUnit.HOURS);
        // 判断当前版本是否处于最新版本
        JSONObject result = new JSONObject();
        CbPcsystemEditionEntity newPcsystemEdition = pcsystemEditionService.getOne(new QueryWrapper<CbPcsystemEditionEntity>().orderByDesc("createtime").last("limit 1"));
        if((newPcsystemEdition == null) || !(loginUser.getEditionName().equals(newPcsystemEdition.getEditionName()))){
            // 不是最新版本
            result.put("pcsystemEdition", newPcsystemEdition.getPcsystemEdition());
        }
        result.put("token", loginToken);
        return ResponseData.success(result);
    }

    @ApiOperation("教师教参网页登陆")
    @PostMapping("/teaccherlogin")
    public ResponseData<JSONObject> teaccherlogin(@RequestBody LoginTeacherEntity loginUser, HttpSession session) {
        //密码账号不能为空
        if(loginUser.getPassword().equals("") || loginUser.getPhone().equals(""))
            return ResponseData.success(UserLoginState.ACCOUNTPWD_NOT_NULL, false);

        // 体验账号 系统生成账号 激活账号
        if (!userService.checkMobileUnique(loginUser.getPhone())) {
            // 手机号没有注册
            return ResponseData.success(UserLoginState.ACCOUNT_NOTEXIT, false);
        }
        LoginUserEntity loginUserEntity = new LoginUserEntity();
        loginUserEntity.setPassword(loginUser.getPassword());
        loginUserEntity.setPhone(loginUser.getPhone());
        TeacherEntity userEntity = userService.pwdlogin(loginUserEntity);
        // 判断账号是否过期或禁用
        if (userEntity == null) {
            // 登录失败
            return ResponseData.success(UserLoginState.PWD_ERROR, false);
        } else if (userEntity.getStatus() == 0) {
            // 账号禁用
            return ResponseData.success(UserLoginState.ACCOUNT_LOCKOREXPIRE, false);
        }
        Date stoptime = userEntity.getStoptime();
        Date nowtime = new Date();
        if (stoptime.compareTo(nowtime) == -1) {
            //账号过期
            return ResponseData.success(UserLoginState.ACCOUNT_LOCKOREXPIRE, false);
        }
        //校验成功正常访问
        //登录成功
        String loginToken = session.getId() + ":" + userEntity.getId();
        redisTemplate.opsForValue().set("user:" + loginToken, userEntity.getId() + "", 2, TimeUnit.HOURS);
        // 判断当前版本是否处于最新版本
        JSONObject result = new JSONObject();
        result.put("token", loginToken);
        return ResponseData.success(result);
    }

    @ApiOperation("登录退出")
    @GetMapping("/loginout")
    @ApiImplicitParam(name = "Authorization",value = "token",paramType = "header",dataType = "String",required = true)
    public ResponseData loginout(@RequestHeader("Authorization") String token) {
        Object user = redisTemplate.opsForValue().get("user:" + token);
        if (user == null){
            // 用户未登录
            return ResponseData.success("请先登录", false);
        }
        long userId = Long.parseLong(user.toString());

        // 记录用户登录日志
        TeacherConfigEntity teacherConfig = teacherConfigService.getFirst(userId);
        // 登录退出
        teacherConfig.setOutcreatetime(new Date());
        long totalTime = (teacherConfig.getOutcreatetime().getTime() - teacherConfig.getIncreatetime().getTime()) / (3600 * 1000);
        teacherConfig.setTotaltime((int)totalTime);
        teacherConfig.setStatus(0);
        teacherConfigService.updateById(teacherConfig);
        //删除redis的用户登陆记录
        redisTemplate.delete("user:" + token);
        //退出登录成功
        return ResponseData.success("退出登录成功", false);
    }

    @ApiOperation("体验账号注册")
    @PostMapping("/register")
    public ResponseData register(@RequestBody RegisterUserEntity registerUserEntity) {

        if (userService.checkMobileUnique(registerUserEntity.getPhone())) {
            //手机号有注册
            return ResponseData.success("手机号已注册", false);
        }

        //开始注册
        //校验验证码
        String code = registerUserEntity.getCode();
        String codeRedisKey = "sms:code:" + registerUserEntity.getPhone();
        String s = redisTemplate.opsForValue().get(codeRedisKey);
        if (!StringUtils.isEmpty(s) && code.equals(s.split("_")[0])) {
            //删除验证码session
            redisTemplate.delete(codeRedisKey);
            //验证码通过，向数据库插入记录
            TeacherEntity teacherEntity = new TeacherEntity();
            teacherEntity.setMobile(registerUserEntity.getPhone());
            //密码加密进行存储
            String encode_password = new BCryptPasswordEncoder().encode(registerUserEntity.getPassword());
            teacherEntity.setPassword(encode_password);
            teacherEntity.setCreatetime(new Date());
            teacherEntity.setMacStatus(1);
            teacherEntity.setStatus(1);
            teacherEntity.setUserType(0);
            // 设置时间往后延迟一个星期
            long nowTime = new Date().getTime();
            long stoptime = nowTime + 7 * 24 * 60 * 60 * 1000;
            teacherEntity.setStoptime(new Date(stoptime));

            userService.save(teacherEntity);
            TeacherEntity teacher = userService.getOne(new QueryWrapper<TeacherEntity>().eq("mobile", registerUserEntity.getPhone()).last("limit 1"));
            //为用户添加mac地址
            MacAddressEntity macAddressEntity = new MacAddressEntity();
            macAddressEntity.setUserId(teacher.getId());
            macAddressEntity.setMacAddress(registerUserEntity.getMac());
            macAddressEntity.setCreateTime(new Date());
            macAddressService.save(macAddressEntity);
            //注册成功回到登录页面
            return ResponseData.success("注册成功！", true);
        } else {
            //校验出错，转发到注册页面
            return ResponseData.success("验证码错误", false);
        }
    }

    /**
     * 发送验证码
     *
     * @param phone
     * @return
     */
    @GetMapping("/sms/sendcode")
    @ApiOperation("根据手机号发送验证码")
    @ApiImplicitParam(name = "phone", value = "手机号码", paramType = "query", dataType = "String", required = true)
    public ResponseData sendCode(@RequestParam("phone") String phone) {
        //接口防刷
        String redisCode = redisTemplate.opsForValue().get("sms:code:" + phone);
        if (!StringUtils.isEmpty(redisCode)) {
            //活动存入redis的时间，用当前时间减去存入redis的时间，判断用户手机号是否在60s内发送验证码
            long currentTime = Long.parseLong(redisCode.split("_")[1]);
            if (System.currentTimeMillis() - currentTime < 60000) {
                //60s内不能再发
                return ResponseData.success("短信验证码频率太高，稍后再试！", false);
            }
        }
        //验证码的再次校验
        String code = ((int)Math.random()*9000+1000)+"";
        String code_redis = code + "_" + System.currentTimeMillis();
        //存入redis，防止同一个手机号在60秒内再次发送验证码
        redisTemplate.opsForValue().set("sms:code:" + phone, code_redis, 1, TimeUnit.MINUTES);
        smsComponent.sendCode(phone, code);
        return ResponseData.success("发送成功", true);
    }

    @ApiOperation("账号激活码注册")
    @PostMapping("/registerbycdk")
    public ResponseData registerbycdk(@RequestBody RegisterUserByCDKEntity registerUserEntity) {
        // 验证激活码
        ActivecodeEntity activecodeEntity = activecodeService.getOne(new QueryWrapper<ActivecodeEntity>().eq("cdk", registerUserEntity.getCdk()).last("limit 1"));
        if (registerUserEntity == null){
            // 激活码没查询到
            return ResponseData.success("激活码有误", false);
        }

        if (userService.checkMobileUnique(registerUserEntity.getPhone())) {
            //手机号有注册
            return ResponseData.success("手机号已注册", false);
        }
        // 设置激活码使用状态
//        activecodeEntity.setStatus(1);
//        activecodeService.update();
        //删除激活码
        activecodeService.removeById(activecodeEntity.getId());

        //开始注册
        //校验验证码
        String code = registerUserEntity.getCode();
        String codeRedisKey = "sms:code:" + registerUserEntity.getPhone();
        String s = redisTemplate.opsForValue().get(codeRedisKey);
        if (!StringUtils.isEmpty(s) && code.equals(s.split("_")[0])) {
            //删除验证码session
            redisTemplate.delete(codeRedisKey);
            //验证码通过，向数据库插入记录
            //查询省市区，若不存在添加
            CityEntity province = cityService.getCityByName(registerUserEntity.getProvince());
            if (province == null) {
                province = new CityEntity();
                province.setCityName(registerUserEntity.getProvince());
                province.setParentid(0);
                cityService.save(province);
            }
            CityEntity city = cityService.getCityByName(registerUserEntity.getCity());
            if (city == null){
                city = new CityEntity();
                city.setCityName(registerUserEntity.getCity());
                city.setParentid(province.getId());
                cityService.save(city);
            }
            CityEntity areaOrCounty = cityService.getCityByName(registerUserEntity.getAreaOrCounty());
            if (areaOrCounty == null){
                areaOrCounty = new CityEntity();
                areaOrCounty.setCityName(registerUserEntity.getAreaOrCounty());
                areaOrCounty.setParentid(city.getId());
                cityService.save(areaOrCounty);
            }

            TeacherEntity teacherEntity = new TeacherEntity();
            teacherEntity.setMobile(registerUserEntity.getPhone());
            //密码加密进行存储
            String encode_password = new BCryptPasswordEncoder().encode(registerUserEntity.getPassword());
            teacherEntity.setPassword(encode_password);
            teacherEntity.setMacStatus(1);
            teacherEntity.setCreatetime(new Date());
            teacherEntity.setStatus(1);
            teacherEntity.setUserType(1);
            teacherEntity.setStoptime(activecodeEntity.getStoptime());
            teacherEntity.setCid(areaOrCounty.getId());
            teacherEntity.setWorkspace(registerUserEntity.getWorkspace());

            userService.save(teacherEntity);
//            TeacherEntity teacher = userService.getOne(new QueryWrapper<TeacherEntity>().eq("mobile", registerUserEntity.getPhone()));
            //为用户添加mac地址
            MacAddressEntity macAddressEntity = new MacAddressEntity();
            macAddressEntity.setUserId(teacherEntity.getId());
            macAddressEntity.setMacAddress(registerUserEntity.getMac());
            macAddressEntity.setCreateTime(new Date());
            macAddressService.save(macAddressEntity);
            //注册成功回到登录页面
            return ResponseData.success("注册成功！", true);
        } else {
            //校验出错，转发到注册页面
            return ResponseData.success("验证码错误", false);
        }
    }
}
